% initialize nidaq hardware interfaces. this is called only once when the gui is
% first initialized.
% xxx - wanted to have re-init incase of nidaqmx call errors, but
% restarting the card will likely screw up ephus, so currently ni failure
% requires quitting and restarting matlab.
function handles = do_init_nidaqmx(handles)

% iniate communication with nidaqmx.
handles.status_str = 'Connecting to nidaqmx';
report_status(handles);

% if task currently exists, remove it
if isfield(handles.nidaqmx,'task')
  status = DAQmxClearTask(handles.nidaqmx.task);
end

% set up a struct for use with the nidaqmx.
% this is used to count frames/lines to initiate sound stimuli.
handles.nidaqmx.params = loadnidaqmx;
p = handles.nidaqmx.params;

task = libpointer('uint32Ptr',false); % for 32 bit
%task = libpointer('uint64Ptr',false); % for 64 bit
status = DAQmxCreateTask(handles.nidaqmx.FRAME_LINE_CTR_TASK_NAME,task);
if status
  handles.error = true;
  handles.error_str = sprintf('nidaqmx: Error creating task: %s',...
    p.defines{find(p.values==status,1,'last')});
  report_error(handles);
else
  % the counter is used to count either the frame or line clock exported by
  % Scanimage so that the stimulus playback can be aligned to one of these
  % clocks, if desired. In the case of User (P0.0) triggering, the counter
  % will still count but is ignored via the mux setting in the RX6 circuit.
  % the counter is armed using the same signal as the external scanimage
  % trigger (generated by ephus). this way the counting will only start at
  % the beginning of a new scanimage acquisition. when the counter reaches
  % zero (always counts down from the number of desired frames or lines) it
  % generates a ttl pulse on the counter output which triggers the RX6
  % playback.
  handles.nidaqmx.task = get(task,'Value');
  status = DAQmxCreateCICountEdgesChan(handles.nidaqmx.task, ...
    handles.nidaqmx.FRAME_LINE_CTR, ...
    handles.nidaqmx.FRAME_LINE_CTR_NAME, ...
    p.values(find(strcmp(p.defines,'DAQmx_Val_Rising'),1)), ...
    handles.start_at, ...
    p.values(find(strcmp(p.defines,'DAQmx_Val_CountDown'),1)));
    handles.nidaqmx.task = get(task,'Value');
  status = DAQmxCreateCICountEdgesChan(handles.nidaqmx.task, ...
    'Counter', ...
    'CounterChan', ...
    p.values(find(strcmp(p.defines,'DAQmx_Val_Rising'),1)), ...
    handles.start_at, ...
    p.values(find(strcmp(p.defines,'DAQmx_Val_CountDown'),1)));
  if status
    handles.error = true;
    handles.error_str = sprintf('nidaqmx: Error adding counter: %s',...
      p.defines{find(p.values==status,1,'last')});
    report_error(handles);
  end
  status = DAQmxExportSignal(handles.nidaqmx.task, ...
    p.values(find(strcmp(p.defines,'DAQmx_Val_CounterOutputEvent'),1)),...
    handles.nidaqmx.FRAME_LINE_CTR_OUT);
  if status
    handles.error = true;
    handles.error_str = sprintf('nidaqmx: Error exporting counter: %s',...
      p.defines{find(p.values==status,1,'last')});
    report_error(handles);
  end
  status = DAQmxSetExportedCtrOutEventOutputBehavior(handles.nidaqmx.task,...
    p.values(find(strcmp(p.defines,'DAQmx_Val_Pulse'),1)));
  status = DAQmxSetExportedCtrOutEventPulsePolarity(handles.nidaqmx.task,...
    p.values(find(strcmp(p.defines,'DAQmx_Val_ActiveHigh'),1)));
  status = DAQmxSetDigEdgeArmStartTrigSrc(handles.nidaqmx.task,... 
    handles.nidaqmx.FRAME_LINE_CTR_ARM);
  status = DAQmxSetDigEdgeArmStartTrigEdge(handles.nidaqmx.task,... 
    p.values(find(strcmp(p.defines,'DAQmx_Val_Rising'),1)));
  status = DAQmxSetArmStartTrigType(handles.nidaqmx.task,... 
    p.values(find(strcmp(p.defines,'DAQmx_Val_DigEdge'),1)));
end

% update hw information application data for callbacks
setappdata(handles.auditoryStim,'nidaqmx',handles.nidaqmx);
